public class Connector<INPUT, OUTPUT, MESSAGE> implements Runnable {
	private Reader<INPUT, MESSAGE> reader;
	private Processor<INPUT, OUTPUT> processor;
	private Writer<OUTPUT> writer;
	private StatusGenerator<INPUT, OUTPUT, MESSAGE> statusGenerator;
	private boolean alive = true;
	public Connector(Reader<INPUT, MESSAGE> reader, Processor<INPUT, OUTPUT> processor, Writer<OUTPUT> writer) {
		setReader(reader);
		setProcessor(processor);
		setWriter(writer);
	}
	public void run() {
		while (isAlive()) {
			Status<MESSAGE> status = null;
			INPUT input = null;
			OUTPUT output = null;
			try {
				input = reader.read();
				output = processor.process(input);
				writer.write(output);
				status = statusGenerator.createStatus(input, output);
			} catch (ReaderException exception) {
				status = statusGenerator.createStatus(exception);
			} catch (ProcessorException exception) {
				status = statusGenerator.createStatus(input, exception);
			} catch (WriterException exception) {
				status = statusGenerator.createStatus(input, output, exception);
			} catch (CommunicationException exception) {
				status = statusGenerator.createStatus(exception);
			} catch (RuntimeException exception) {
				status = statusGenerator.createStatus(exception);
			} catch (Exception exception) {
				status = statusGenerator.createStatus(exception);
			} finally {
				reader.reportStatus(status);
			}
		}
	}
	public Reader<INPUT, MESSAGE> getReader() {
		return reader;
	}
	public void setReader(Reader<INPUT, MESSAGE> reader) {
		this.reader = reader;
	}
	public Processor<INPUT, OUTPUT> getProcessor() {
		return processor;
	}
	public void setProcessor(Processor<INPUT, OUTPUT> processor) {
		this.processor = processor;
	}
	public Writer<OUTPUT> getWriter() {
		return writer;
	}
	public void setWriter(Writer<OUTPUT> writer) {
		this.writer = writer;
	}
	public StatusGenerator<INPUT, OUTPUT, MESSAGE> getStatusGenerator() {
		return statusGenerator;
	}
	public void setStatusGenerator(StatusGenerator<INPUT, OUTPUT, MESSAGE> statusGenerator) {
		this.statusGenerator = statusGenerator;
	}
	public boolean isAlive() {
		return alive;
	}
	public void setAlive(boolean alive) {
		this.alive = alive;
	}
}

